package city.spring.modules.system.service.impl;

import city.spring.modules.ext.EntityExtUtils;
import city.spring.modules.ext.entity.GroupPermissionExt;
import city.spring.modules.ext.entity.GroupRoleExt;
import city.spring.modules.ext.entity.UserGroupExt;
import city.spring.modules.ext.service.GroupPermissionExtService;
import city.spring.modules.ext.service.GroupRoleExtService;
import city.spring.modules.ext.service.UserGroupExtService;
import city.spring.modules.system.entity.GroupEntity;
import city.spring.modules.system.entity.PermissionEntity;
import city.spring.modules.system.entity.RoleEntity;
import city.spring.modules.system.repository.GroupRepository;
import city.spring.modules.system.service.GroupService;
import city.spring.modules.system.service.PermissionService;
import city.spring.modules.system.service.RoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 用户组信息服务
 *
 * @author HouKunLin
 * @date 2019/12/8 0008 14:51
 */
@CacheConfig(cacheNames = {GroupServiceImpl.CACHE_NAME})
@Transactional(rollbackFor = Throwable.class)
@Service
public class GroupServiceImpl extends ServiceImpl<GroupRepository, GroupEntity> implements GroupService {
    public final static String CACHE_NAME = "group";
    private final RoleService roleService;
    private final PermissionService permissionService;
    private final GroupRoleExtService groupRoleExtService;
    private final GroupPermissionExtService groupPermissionExtService;
    private final UserGroupExtService userGroupExtService;

    public GroupServiceImpl(RoleService roleService, PermissionService permissionService, GroupRoleExtService groupRoleExtService, GroupPermissionExtService groupPermissionExtService, UserGroupExtService userGroupExtService) {
        this.roleService = roleService;
        this.permissionService = permissionService;
        this.groupRoleExtService = groupRoleExtService;
        this.groupPermissionExtService = groupPermissionExtService;
        this.userGroupExtService = userGroupExtService;
    }

    @Cacheable(key = "'list:authority:userId:'+#userId")
    @Override
    public List<GroupEntity> getUserGroupsWithAuthority(String userId) {
        List<GroupEntity> groups = baseMapper.getUserGroups(userId);
        for (GroupEntity group : groups) {
            loadRoles(group);
            loadPermissions(group);
        }
        return groups;
    }

    @Cacheable(key = "'list:info:userId:'+#userId")
    @Override
    public List<GroupEntity> getUserGroups(String userId) {
        return baseMapper.getUserGroups(userId);
    }

    @Override
    public void loadPermissions(GroupEntity entity) {
        entity.setPermissions(permissionService.getGroupPermissions(entity.getId()));
    }

    @Override
    public void loadPermissions(List<GroupEntity> entities) {
        entities.forEach(this::loadPermissions);
    }

    @Override
    public void loadRoles(GroupEntity entity) {
        entity.setRoles(roleService.getGroupRolesWithAuthority(entity.getId()));
    }

    @Override
    public void loadRoles(List<GroupEntity> entities) {
        entities.forEach(this::loadRoles);
    }

    @Override
    public GroupEntity getGroupInfo(String primaryKey, boolean loadPermissions, boolean loadRoles) {
        GroupEntity entity = getById(primaryKey);
        if (loadPermissions) {
            loadPermissions(entity);
        }
        if (loadRoles) {
            loadRoles(entity);
        }
        return entity;
    }

    @Override
    public void saveGroup(GroupEntity entity) {
        boolean save = save(entity);
        if (!save) {
            throw new RuntimeException("保存用户组信息失败");
        }
        // repairRelation(entity);
    }

    @Override
    public void updateGroup(GroupEntity entity) {
        boolean update = updateById(entity);
        if (!update) {
            throw new RuntimeException("修改用户组信息失败");
        }
        // repairRelation(entity);
    }

    @Override
    public void deleteGroup(String primaryKey) {
        removeById(primaryKey);
        groupRoleExtService.lambdaUpdate().eq(GroupRoleExt::getGroupId, primaryKey).remove();
        groupPermissionExtService.lambdaUpdate().eq(GroupPermissionExt::getGroupId, primaryKey).remove();
        userGroupExtService.lambdaUpdate().eq(UserGroupExt::getRelatedId, primaryKey).remove();
    }

    @Override
    public void deleteGroup(List<String> primaryKeys) {
        removeByIds(primaryKeys);
        groupRoleExtService.lambdaUpdate().in(GroupRoleExt::getGroupId, primaryKeys).remove();
        groupPermissionExtService.lambdaUpdate().in(GroupPermissionExt::getGroupId, primaryKeys).remove();
        userGroupExtService.lambdaUpdate().in(UserGroupExt::getRelatedId, primaryKeys).remove();
    }

    /**
     * 维护 <strong>用户组信息</strong> 的 角色列表、权限列表
     *
     * @param entity <strong>用户组信息</strong>
     */
    private void repairRelation(GroupEntity entity) {
        EntityExtUtils.repairRelation(groupRoleExtService, entity,
                GroupEntity::getId, GroupEntity::getRoles, RoleEntity::getId,
                GroupRoleExt::new, GroupRoleExt::getGroupId);

        EntityExtUtils.repairRelation(groupPermissionExtService, entity,
                GroupEntity::getId, GroupEntity::getPermissions, PermissionEntity::getId,
                GroupPermissionExt::new, GroupPermissionExt::getGroupId);
    }

    @Override
    public void setGroupRoles(GroupEntity entity) {
        EntityExtUtils.repairRelation(groupRoleExtService, entity,
                GroupEntity::getId, GroupEntity::getRoles, RoleEntity::getId,
                GroupRoleExt::new, GroupRoleExt::getGroupId);
    }

    @Override
    public void setGroupPermissions(GroupEntity entity) {
        EntityExtUtils.repairRelation(groupPermissionExtService, entity,
                GroupEntity::getId, GroupEntity::getPermissions, PermissionEntity::getId,
                GroupPermissionExt::new, GroupPermissionExt::getGroupId);
    }
}
